package configs

import (
	"fmt"
	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
	"os"
	"path/filepath"
	"strings"
)

// Conf 定义配置的全局变量
var Conf = new(AppConfig)

type AppConfig struct {
	Name    string `mapstructure:"name"`
	Version string `mapstructure:"version"`
	Mode    string `mapstructure:"mode"`
	Address string `mapstructure:"address"`

	*LogConfig   `mapstructure:"log"`
	*MySQLConfig `mapstructure:"mysql"`
}

type LogConfig struct {
	Level      string `mapstructure:"level"`
	Filename   string `mapstructure:"filename"`
	MaxSize    int    `mapstructure:"max_size"`
	MaxAge     int    `mapstructure:"max_age"`
	MaxBackups int    `mapstructure:"max_backups"`
}

type MySQLConfig struct {
	Host         string `mapstructure:"host"`
	User         string `mapstructure:"user"`
	Password     string `mapstructure:"password"`
	DB           string `mapstructure:"dbname"`
	Port         int    `mapstructure:"port"`
	MaxOpenConns int    `mapstructure:"max_open_conns"`
	MaxIdleConns int    `mapstructure:"max_idle_conns"`
	LogModel     bool   `mapstructure:"log_model"`
}

// Init 配置初始化
func InitConfig() (err error) {

	filePath, _ := getConfigFilePath()

	// 指定配置文件路径
	viper.SetConfigFile(filePath)

	// 读取配置信息
	err = viper.ReadInConfig()
	if err != nil {
		// 读取配置信息失败
		fmt.Printf("viper.ReadInConfig failed, err:%v\n", err)
		return
	}

	// 把读取到的配置信息反序列化到 Conf 变量中
	if err := viper.Unmarshal(Conf); err != nil {
		fmt.Printf("viper.Unmarshal failed, err:%v\n", err)
		return err
	}
	// 监听配置文件变化
	viper.WatchConfig()

	// 当使用结构体变量存储配置的时候，需要在配置发生变更后手动更新一下结构体变量
	viper.OnConfigChange(func(in fsnotify.Event) {
		fmt.Println("配置文件修改了...")
		if err := viper.Unmarshal(Conf); err != nil {
			fmt.Printf("viper.Unmarshal failed, err:%v\n", err)
		}
	})
	return nil
}

func getConfigFilePath() (string, error) {

	// 获取环境变量
	env := os.Getenv("ENV")
	if env == "" {
		env = "DEV"
	}

	// 根据环境确定配置文件名称
	var fileName string
	if env == "PRO" {
		fileName = "configs.yaml"
	} else {
		fileName = fmt.Sprintf("config_%s.yaml", strings.ToLower(env))
	}

	// 获取当前工作目录的绝对路径
	currentDir, _ := os.Getwd()
	configDir := "configs"
	filePath := fmt.Sprintf("%s/%s", configDir, fileName)
	configFilePath := filepath.Join(currentDir, filePath)

	fmt.Println("Current configs path:", configFilePath)
	return configFilePath, nil
}
